
interface SunriseSunsetResult {
    sunrise: string;
    sunset: string;
    solarNoon: string;
    isPolarDay?: boolean;
    isPolarNight?: boolean;
}

export function calculateSunriseSunset(
    lat: number,
    lng: number,
    date: Date,
    elevation: number = 0  // 新增海拔参数（单位：米）
): SunriseSunsetResult {
    const utcDate = adjustDateToUTCSolarNoon(date, lng);
    const { declination, equationOfTime } = calculateSolarParameters(utcDate);
    
    // 传入海拔参数计算时角
    const hourAngle = calculateSunHourAngle(lat, declination, elevation);
    
    if (hourAngle === null) {
        return {
            sunrise: "N/A",
            sunset: "N/A",
            solarNoon: formatSolarTime(12, 0),
            ...(declination > 0 ? { isPolarDay: true } : { isPolarNight: true })
        };
    }

    const solarNoonUTC = 12 - lng/15 + equationOfTime;
    const sunriseUTC = solarNoonUTC - hourAngle/15;
    const sunsetUTC = solarNoonUTC + hourAngle/15;

    return {
        sunrise: convertUTCTimeToSolar(sunriseUTC),
        sunset: convertUTCTimeToSolar(sunsetUTC),
        solarNoon: formatSolarTime(12, 0)
    };
}

// 添加海拔修正的时角计算
function calculateSunHourAngle(
    lat: number,
    declination: number,
    elevation: number = 0
): number | null {
    // 使用Saemundsson公式计算太阳视地平角修正
    const θ = calculateSolarElevationAngle(elevation);
    
    const latRad = degToRad(lat);
    const decRad = degToRad(declination);
    
    const cosHourAngle = 
        (Math.sin(degToRad(θ)) - Math.sin(latRad)*Math.sin(decRad)) 
        / (Math.cos(latRad)*Math.cos(decRad));
    
    if (cosHourAngle > 1) return null;   // 极夜
    if (cosHourAngle < -1) return null;  // 极昼
    
    return radToDeg(Math.acos(cosHourAngle));
}

// 新增：海拔修正计算（Saemundsson公式）
function calculateSolarElevationAngle(elevation: number): number {
    // 基础地平角（考虑大气折射）
    const baseAngle = -0.833;
    // 海拔修正项（单位：度）
    const elevationAdjustment = (2.076 * Math.sqrt(elevation)) / 60;
    return baseAngle - elevationAdjustment;
}



// 修正时差计算（更精确的公式）
function calculateSolarParameters(date: Date) {
    const d = (date.getTime() - Date.UTC(2000, 0, 1, 12)) / (1000 * 3600 * 24);
    
    // 太阳几何平均黄经
    const L = (280.466 + 0.9856474 * d) % 360;
    
    // 太阳平近点角
    const M = (357.529 + 0.9856003 * d) % 360;
    const M_rad = degToRad(M);
    
    // 黄经方程
    const C = (1.915 * Math.sin(M_rad) 
             + 0.020 * Math.sin(2*M_rad)) * (1 - 0.00004*d);
    
    // 太阳真实黄经
    const λ = (L + C + 180) % 360; 
    
    // 太阳赤纬（精确计算）
    const ε = 23.439 - 0.0000004 * d; // 黄赤交角
    const δ = radToDeg(Math.asin(
        Math.sin(degToRad(λ)) * Math.sin(degToRad(ε))
    ));
    
    // 时差（分钟）
    const EoT = (L - 0.0057183 - λ + 180) * 4; // 转换为分钟
    const equationOfTime = EoT / 60; // 转换为小时
    
    return { declination: δ, equationOfTime };
}

// 修正UTC日期转换逻辑
function adjustDateToUTCSolarNoon(localDate: Date, lng: number): Date {
    // 计算当地正午对应的UTC时间
    const utcMidnight = new Date(Date.UTC(
        localDate.getFullYear(),
        localDate.getMonth(),
        localDate.getDate()
    ));
    const offset = 12 - lng/15; // 正午UTC = 当地12点 - 经度偏移
    return new Date(utcMidnight.getTime() + offset * 3600 * 1000);
}

// 简化时间转换
function convertUTCTimeToSolar(utcHours: number): string {
    utcHours = ((utcHours % 24) + 24) % 24; // 标准化
    const hours = Math.floor(utcHours);
    const minutes = Math.round((utcHours - hours) * 60);
    return formatSolarTime(hours, minutes);
}

function formatSolarTime(hours: number, minutes: number): string {
    const period = hours >= 12 ? 'PM' : 'AM';
    const twelveHour = hours % 12 || 12;
    return `${twelveHour}:${minutes.toString().padStart(2, '0')} ${period}`;
}

// 单位转换
const degToRad = (deg: number) => deg * Math.PI / 180;
const radToDeg = (rad: number) => rad * 180 / Math.PI;